<?php
/*
Extension Name: Private Messages
Extension Url: http://lussumo.com/addons/index.php?PostBackAction=AddOn&AddOnID=220
Description: Turn your whispers into an Inbox/Outbox Private Messaging system
Version: 1.2.beta
Author: Vanilla-Friends
Author Url: http://code.google.com/p/vanilla-friends/

Changes

Version 1.1 - 14.12.2006, Jazzman
- Original Whisper system will now be deactivated by default
- From/To column will now always display the 'other' username you have whispered to, or who has whispered you
- 'Send private messages' link added to profile page (uses 'SendTo' from URL querystring)
- Added user preference to receive an email notification when you have a new private message
*/

$Context->SetDefinition('ExtensionOptions', 'Extension Options');
$Context->SetDefinition('PrivateMessagesSettings', 'Private Messages');
$Context->SetDefinition('PrivateMessagesCategory', 'Private Messages Category');
$Context->SetDefinition('PrivateMessagesCategoryNotes', 'Select a category which will contain all private messages. Configure this category so no one can view it.');
$Context->SetDefinition('SelectPrivateMessagesCategory', 'Please select a category for Private Messages at the settings page');
$Context->SetDefinition('PrivateMessagesTab', 'Inbox');
$Context->SetDefinition('SendPrivateMessage', 'Send private message');
$Context->SetDefinition('PrivateMessages', 'Private Messages');
$Context->SetDefinition('Inbox', 'Inbox');
$Context->SetDefinition('SentMail', 'Sent Mail');
$Context->SetDefinition('NoPrivateMessagesFound', 'No Private Messages found');
$Context->SetDefinition('MessageTo', 'To (enter a username)');
$Context->SetDefinition('MessageSubject', 'Subject');
$Context->SetDefinition('MessageBody', 'Enter your message');
$Context->SetDefinition('ErrWhisperUsernameMandatory', 'You must provide a username where you want to send your message to');
$Context->SetDefinition('Options', 'Options');
$Context->SetDefinition('PrivateMessageNotification', 'Receive email notifications upon new private messages');
$Context->SetDefinition('ReceiveNewPrivateMessage', 'You have a new private message');

$Context->Configuration['PRIVATE_MESSAGES_DISABLE_WHISPERS'] = '1';


if (!array_key_exists('PRIVATE_MESSAGES_CATEGORY_ID', $Configuration)) {
	AddConfigurationSetting($Context, 'PRIVATE_MESSAGES_CATEGORY_ID', '0');
	AddConfigurationSetting($Context, 'TAB_POSITION_PRIVATE_MESSAGES', '100');
	AddConfigurationSetting($Context, 'PRIVATE_MESSAGES_PER_PAGE', '30');

} elseif (ForceInt($Configuration['PRIVATE_MESSAGES_CATEGORY_ID'], 0) == 0) {

	// Add notice
	$NoticeCollector->AddNotice($Context->GetDefinition('SelectPrivateMessagesCategory'));

}

// User must be logged in to see the PM tab
if ($Context->Session->UserID > 0 && ForceInt($Configuration['PRIVATE_MESSAGES_CATEGORY_ID'], 0) > 0) {

	class PrivateMessages {
		var $Name;
		var $Context;

		function PrivateMessages(&$Context) {
			$this->Name = 'PrivateMessages';
			$this->Context = &$Context;
			$this->UserID = $this->Context->Session->UserID;
			$this->CategoryID = ForceInt($this->Context->Configuration['PRIVATE_MESSAGES_CATEGORY_ID'], 0);
		}

		function GetNewMessagesCount() {
			$TotalNumberOfRecords = 0;
			$s = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
			$s->SetMainTable('Discussion', 't');
			$s->AddSelect('DiscussionID', 't', 'Count', 'count');
			$s->AddJoin('UserDiscussionWatch', 'utw', 'DiscussionID', 't', 'DiscussionID', 'left join', ' and utw.'.$this->Context->DatabaseColumns['UserDiscussionWatch']['UserID'].' = '.$this->UserID);
			$s->AddWhere('utw', 'CountComments', 't', 'CountComments', '<', 'and', '', 0);
			$s->AddWhere('t', 'Active', '', '1', '=');
			$s->AddWhere('t', 'CategoryID', '', $this->CategoryID, '=');
			$s->AddWhere('t', 'WhisperUserID', '', $this->UserID, '=', 'and', '', 1, 1);
			$s->AddWhere('t', 'AuthUserID', '', $this->UserID, '=', 'or');
			$s->EndWhereGroup();
			$Result = $this->Context->Database->Select($s, $this->Name, 'GetNewMessagesCount', 'An error occurred while attempting to retrieve PM information.');
			while ($Row = $this->Context->Database->GetRow($Result)) {
				$TotalNumberOfRecords = $Row['Count'];
			}
			return $TotalNumberOfRecords;
		}

		function GetDiscussionBuilder($s = 0) {
			if (!$s) $s = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
			$s->SetMainTable('Discussion', 't');
			$s->AddSelect(array('DiscussionID', 'FirstCommentID', 'AuthUserID', 'WhisperUserID', 'Active', 'Closed', 'Sticky', 'Sink', 'Name', 'DateCreated', 'LastUserID', 'DateLastActive', 'CountComments', 'CategoryID'), 't');
			$s->AddJoin('User', 'u', 'UserID', 't', 'AuthUserID', 'left join');
			$s->AddSelect('Name', 'u', 'AuthUsername');
			$s->AddJoin('User', 'lu', 'UserID', 't', 'LastUserID', 'left join');
			$s->AddSelect('Name', 'lu', 'LastUsername');
			$s->AddJoin('User', 'wt', 'UserID', 't', 'WhisperUserID', 'left join');
			$s->AddSelect('Name', 'wt', 'WhisperUsername');
			$s->AddGroupBy('DiscussionID', 't');
			$s->AddJoin('Category', 'c', 'CategoryID', 't', 'CategoryID', 'left join');
			$s->AddSelect('Name', 'c', 'Category');
			$s->AddJoin('UserBookmark', 'b', 'DiscussionID', 't', 'DiscussionID', 'left join', ' and b.'.$this->Context->DatabaseColumns['UserBookmark']['UserID'].' = '.$this->Context->Session->UserID);
			$s->AddSelect('DiscussionID', 'b', 'Bookmarked', '', '', 0, ' is not null');
			$s->AddJoin('UserDiscussionWatch', 'utw', 'DiscussionID', 't', 'DiscussionID', 'left join', ' and utw.'.$this->Context->DatabaseColumns['UserDiscussionWatch']['UserID'].' = '.$this->Context->Session->UserID);
			$s->AddSelect('LastViewed', 'utw');
			$s->AddSelect('CountComments', 'utw', 'LastViewCountComments', 'coalesce', '0');

			return $s;
		}

		function GetDiscussionById($DiscussionID, $RecordDiscussionView = '0') {
			$RecordDiscussionView = ForceBool($RecordDiscussionView, 0);
			$Discussion = $this->Context->ObjectFactory->NewContextObject($this->Context, 'Discussion');
			$s = $this->GetDiscussionBuilder();
			$s->AddWhere('t', 'DiscussionID', '', $DiscussionID, '=');
			// temp fix for PM so only sender or receiver can see message
			$s->AddWhere('t', 'AuthUserID', '', $this->UserID, '=','and','','',1);
			$s->AddWhere('t', 'WhisperUserID', '', $this->UserID, '=','or');
			$s->EndWhereGroup();

			$result = $this->Context->Database->Select($s, $this->Name, 'GetDiscussionById', 'An error occurred while attempting to retrieve the requested discussion.');
			if ($this->Context->Database->RowCount($result) == 0) {
				$this->Context->WarningCollector->Add($this->Context->GetDefinition('ErrDiscussionNotFound'));
				$Discussion = false;
			}
			while ($rows = $this->Context->Database->GetRow($result)) {
				$Discussion->GetPropertiesFromDataSet($rows, $this->Context->Configuration);
			}
			if ($Discussion && $RecordDiscussionView) {
				$s->Clear();
				$s->SetMainTable('UserDiscussionWatch', 'utw');
				$s->AddFieldNameValue('CountComments', $Discussion->CountComments);
				$s->AddFieldNameValue('LastViewed', MysqlDateTime());
				if ($Discussion->LastViewed == '') {
					$s->AddFieldNameValue('UserID', $this->Context->Session->UserID);
					$s->AddFieldNameValue('DiscussionID', $DiscussionID);
					$this->Context->Database->Insert($s, $this->Name, 'GetDiscussionById', 'An error occurred while recording this discussion viewing.', 0, 0);
				} else {
					$s->AddWhere('utw', 'UserID', '', $this->Context->Session->UserID, '=');
					$s->AddWhere('utw', 'DiscussionID', '', $Discussion->DiscussionID, '=');
					$this->Context->Database->Update($s, $this->Name, 'GetDiscussionById', 'An error occurred while recording this discussion viewing.', 0);
				}
			}
			return $Discussion;
		}

		function GetDiscussionCount($View) {
			$TotalNumberOfRecords = 0;
			$s = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
			$s->SetMainTable('Discussion', 't');
			$s->AddJoin('UserBookmark', 'b', 'DiscussionID', 't', 'DiscussionID', 'left join', ' and b.'.$this->Context->DatabaseColumns['UserBookmark']['UserID'].' = '.$this->Context->Session->UserID);
			$s->AddSelect('DiscussionID', 't', 'Count', 'count');
			$s->AddWhere('t', 'Active', '', '1', '=');
			$s->AddWhere('t', 'CategoryID', '', $this->CategoryID, '=');
			if ($View == 'Inbox') {
				$s->AddWhere('t', 'WhisperUserID', '', $this->UserID, '=');
			} else {
				$s->AddWhere('t', 'AuthUserID', '', $this->UserID, '=');
			}
			$result = $this->Context->Database->Select($s, $this->Name, 'GetDiscussionCount', 'An error occurred while retrieving Discussion information.');
			while ($rows = $this->Context->Database->GetRow($result)) {
				$TotalNumberOfRecords = $rows['Count'];
			}
			return $TotalNumberOfRecords;
		}

		function GetDiscussionList($RowsPerPage, $CurrentPage, $View) {
			$TotalNumberOfRecords = 0;
			if ($RowsPerPage > 0) {
				$CurrentPage = ForceInt($CurrentPage, 1);
				if ($CurrentPage < 1) $CurrentPage == 1;
				$RowsPerPage = ForceInt($RowsPerPage, 50);
				$FirstRecord = ($CurrentPage * $RowsPerPage) - $RowsPerPage;
			}

			$s = $this->GetDiscussionBuilder();
			$s->AddJoin('Comment', 'm', 'CommentID', 't', 'FirstCommentID', 'join');
			$s->AddSelect('Body', 'm');
			$s->AddWhere('t', 'Active', '', '1', '=');
			$s->AddWhere('t', 'CategoryID', '', $this->CategoryID, '=');

			if ($View == 'Inbox') {
				$s->AddWhere('t', 'WhisperUserID', '', $this->UserID, '=', 'and', '', 1, 1);
				$s->AddWhere('t', 'AuthUserID', '', $this->UserID, '=', 'or');
				$s->EndWhereGroup();
			} else {
				$s->AddWhere('t', 'AuthUserID', '', $this->UserID, '=');
			}
			$s->AddOrderBy('DateLastActive', 't', 'desc');

			if ($RowsPerPage > 0) $s->AddLimit($FirstRecord, $RowsPerPage);
			return $this->Context->Database->Select($s, $this->Name, 'GetDiscussionList', 'An error occurred while retrieving discussions.');
		}

		function GetCommentBuilder($s = 0) {
			if (!$s) $s = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
			$s->SetMainTable('Comment', 'm');
			$s->AddJoin('User', 'a', 'UserID', 'm', 'AuthUserID', 'inner join');
			$s->AddJoin('Role', 'r', 'RoleID', 'a', 'RoleID', 'left join');
			$s->AddJoin('User', 'e', 'UserID', 'm', 'EditUserID', 'left join');
			$s->AddJoin('User', 'd', 'UserID', 'm', 'DeleteUserID', 'left join');
			$s->AddJoin('Discussion', 't', 'DiscussionID', 'm', 'DiscussionID', 'inner join');
			$s->AddJoin('User', 'w', 'UserID', 'm', 'WhisperUserID', 'left join');
			$s->AddSelect(array('CommentID', 'DiscussionID', 'Body', 'FormatType', 'DateCreated', 'DateEdited', 'DateDeleted', 'Deleted', 'AuthUserID', 'EditUserID', 'DeleteUserID', 'WhisperUserID', 'RemoteIp'), 'm');
			$s->AddSelect('Name', 'a', 'AuthUsername');
			$s->AddSelect('Icon', 'a', 'AuthIcon');
			$s->AddSelect('Name', 'r', 'AuthRole');
			$s->AddSelect('RoleID', 'r', 'AuthRoleID');
			$s->AddSelect('Description', 'r', 'AuthRoleDesc');
			$s->AddSelect('Icon', 'r', 'AuthRoleIcon');
			$s->AddSelect('PERMISSION_HTML_ALLOWED', 'r', 'AuthCanPostHtml');
			$s->AddSelect('Name', 'e', 'EditUsername');
			$s->AddSelect('Name', 'd', 'DeleteUsername');
			$s->AddSelect('WhisperUserID', 't', 'DiscussionWhisperUserID');
			$s->AddSelect('Name', 'w', 'WhisperUsername');
			return $s;
		}

		function GetCommentCount($DiscussionID) {
			$TotalNumberOfRecords = 0;
			$DiscussionID = ForceInt($DiscussionID, 0);
			$s = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
			$s->SetMainTable('Comment', 'm');
			$s->AddJoin('Discussion', 't', 'DiscussionID', 'm', 'DiscussionID', 'inner join');
			if (!$this->Context->Session->User->Permission('PERMISSION_VIEW_HIDDEN_COMMENTS')
				|| !$this->Context->Session->User->Preference('ShowDeletedComments')) {
				$s->AddWhere('m', 'Deleted', '', 0, '=', 'and', '', 1, 1);
				$s->AddWhere('m', 'Deleted', '', 0, '=', 'or', '' ,0);
				$s->EndWhereGroup();
			}
			$s->AddSelect('CommentID', 'm', 'Count', 'count');
			$s->AddWhere('m', 'WhisperUserID', '', $this->Context->Session->UserID, '=', 'and', '', 1, 1);
			$s->AddWhere('m', 'WhisperUserID', '', 'null', 'is', 'or', '', 0);
			$s->AddWhere('m', 'WhisperUserID', '', '0', '=', 'or', '', 0);
			$s->AddWhere('m', 'WhisperUserID', '', '0', '=', 'or', '', 1);
			$s->AddWhere('m', 'AuthUserID', '', $this->Context->Session->UserID, '=', 'or');
			$s->EndWhereGroup();
			$s->AddWhere('m', 'DiscussionID', '', $DiscussionID, '=');
			$result = $this->Context->Database->Select($s, $this->Name, 'GetCommentCount', 'An error occurred while retrieving comment information.');
			while ($rows = $this->Context->Database->GetRow($result)) {
				$TotalNumberOfRecords = $rows['Count'];
			}
			return $TotalNumberOfRecords;
		}

		function GetCommentList($RowsPerPage, $CurrentPage, $DiscussionID) {
			$RowsPerPage = ForceInt($RowsPerPage, 50);
			$CurrentPage = ForceInt($CurrentPage, 1);
			$DiscussionID = ForceInt($DiscussionID, 0);

			if ($RowsPerPage > 0) {
				$CurrentPage = ForceInt($CurrentPage, 1);
				if ($CurrentPage < 1) $CurrentPage == 1;
				$RowsPerPage = ForceInt($RowsPerPage, 50);
				$FirstRecord = ($CurrentPage * $RowsPerPage) - $RowsPerPage;
			}

			$s = $this->GetCommentBuilder();
			if (!$this->Context->Session->User->Permission('PERMISSION_VIEW_HIDDEN_COMMENTS')
				|| !$this->Context->Session->User->Preference('ShowDeletedComments')) {
				$s->AddWhere('m', 'Deleted', '', 0, '=', 'and', '', 1, 1);
				$s->AddWhere('m', 'Deleted', '', 0, '=', 'or', '' ,0);
				$s->EndWhereGroup();
			}

			$s->AddWhere('m', 'WhisperUserID', '', $this->Context->Session->UserID, '=', 'and', '', 1, 1);
			$s->AddWhere('m', 'WhisperUserID', '', 'null', 'is', 'or', '', 0);
			$s->AddWhere('m', 'WhisperUserID', '', '0', '=', 'or', '', 0);
			$s->AddWhere('m', 'WhisperUserID', '', '0', '=', 'or', '', 1);
			$s->AddWhere('m', 'AuthUserID', '', $this->Context->Session->UserID, '=', 'or');
			$s->EndWhereGroup();

			$s->AddWhere('m', 'DiscussionID', '', $DiscussionID, '=');
			$s->AddOrderBy('DateCreated', 'm', 'asc');
			if ($RowsPerPage > 0) $s->AddLimit($FirstRecord, $RowsPerPage);

			return $this->Context->Database->Select($s, $this->Name, 'GetCommentList', 'An error occurred while attempting to retrieve the requested comments.');
		}

		function SendNotification($SendToUserID) {
			$UserManager = $this->Context->ObjectFactory->NewContextObject($this->Context, 'UserManager');
			$User = $UserManager->GetUserById($SendToUserID);
			if ($User) {
				if ($User->Preference('PrivateMessageNotification')) {
					$e = $this->Context->ObjectFactory->NewContextObject($this->Context, 'Email');
					$e->HtmlOn = 0;
					$e->WarningCollector = &$this->Context->WarningCollector;
					$e->ErrorManager = &$this->Context->ErrorManager;
					$e->AddFrom($this->Context->Configuration['SUPPORT_EMAIL'], $this->Context->Configuration['SUPPORT_NAME']);
					$e->AddRecipient($User->Email, $User->Name);
					$e->Subject = $this->Context->Configuration['APPLICATION_TITLE'].' '.$this->Context->GetDefinition('ReceiveNewPrivateMessage');

					$File = dirname(__FILE__) . '/email_new_message.txt';
					$EmailBody = @file_get_contents($File);

					if (!$EmailBody) $this->Context->ErrorManager->AddError($this->Context, $this->Name, 'SendNotification', 'Failed to read email template ('.$File.').');

					$e->Body = str_replace(
						array(
							"{user_name}",
							"{forum_name}",
							"{user_from}",
							"{forum_url}"
						),
						array(
							$User->Name,
							$this->Context->Configuration['APPLICATION_TITLE'],
							$this->Context->Session->User->Name,
							ConcatenatePath(
								$this->Context->Configuration['BASE_URL'],
								GetUrl($Configuration, 'extension.php', '', '', '', '', 'PostBackAction=PrivateMessages')
							)
						),
						$EmailBody
					);

					// Send the email
					$e->Send();
				}
			}
		}
	}

	class PrivateMessagesGrid extends Control {
		var $PageJump;
		var $CurrentPage;
		var $DiscussionData;
		var $DiscussionDataCount;

		function PrivateMessagesGrid(&$Context) {
			$this->Name = 'PrivateMessagesGrid';
			$this->Control($Context);
			$this->View = ForceIncomingString('View', 'Inbox');
			$this->CurrentPage = ForceIncomingInt('page', 1);
			$this->DiscussionData = false;
			$this->DiscussionDataCount = false;

			$PrivateMessages = $Context->ObjectFactory->NewContextObject($Context, 'PrivateMessages');
			$this->DiscussionData = $PrivateMessages->GetDiscussionList($this->Context->Configuration['DISCUSSIONS_PER_PAGE'], $this->CurrentPage, $this->View);
			$this->DiscussionDataCount = $PrivateMessages->GetDiscussionCount($this->View);
			$this->Context->PageTitle = $this->Context->GetDefinition($this->View);
		}

		function Render() {
			$this->CallDelegate('PreRender');

			$pl = $this->Context->ObjectFactory->NewContextObject($this->Context, 'PageList');
			$pl->NextText = $this->Context->GetDefinition('Next');
			$pl->PreviousText = $this->Context->GetDefinition('Previous');
			$pl->CssClass = 'PageList';
			$pl->TotalRecords = $this->DiscussionDataCount;
			$pl->CurrentPage = $this->CurrentPage;
			$pl->RecordsPerPage = $this->Context->Configuration['PRIVATE_MESSAGES_PER_PAGE'];
			$pl->PagesToDisplay = 10;
			$pl->PageParameterName = 'page';
			$pl->DefineProperties();
			$PageDetails = $pl->GetPageDetails($this->Context);
			$PageList = $pl->GetNumericList();

			include(dirname(__FILE__) . '/message_grid.php');
			$this->CallDelegate('PostRender');
		}
	}

	class PrivateMessageView extends Control {
		var $PageJump;
		var $CurrentPage;
		var $Discussion;
		var $CommentData;
		var $CommentDataCount;
		var $pl;

		function PrivateMessageView(&$Context) {
			$this->Name = 'PrivateMessageView';
			$this->Control($Context);
			$this->CurrentPage = ForceIncomingInt('page', 1);
			$this->DiscussionID = ForceIncomingInt('DiscussionID', 0);

			// Load information about this discussion
			$PrivateMessages = $this->Context->ObjectFactory->NewContextObject($this->Context, 'PrivateMessages');
			$RecordDiscussionView = 1;
			if ($this->Context->Session->UserID == 0) $RecordDiscussionView = 0;
			$this->Discussion = $PrivateMessages->GetDiscussionById($this->DiscussionID, $RecordDiscussionView);
			if ($this->Discussion) {
				$this->Discussion->FormatPropertiesForDisplay();
				if (!$this->Discussion->Active && !$this->Context->Session->User->Permission('PERMISSION_HIDE_DISCUSSIONS')) {
					$this->Discussion = false;
					$this->Context->WarningCollector->Add($this->Context->GetDefinition('ErrDiscussionNotFound'));
				}
			}

			if ($this->Context->WarningCollector->Count() > 0) {
				$this->CommentData = false;
				$this->CommentDataCount = 0;
			} else {
				// Load the data
				$this->CommentDataCount = $PrivateMessages->GetCommentCount($this->DiscussionID);

				// If trying to focus on a particular comment, make sure to look at the correct page
				$Focus = ForceIncomingInt('Focus', 0);
				$PageCount = CalculateNumberOfPages($this->CommentDataCount, $this->Context->Configuration['COMMENTS_PER_PAGE']);
				if ($Focus > 0 && $PageCount > 1) {
					$this->CurrentPage = 1;
					$FoundComment = 0;
					while ($this->CurrentPage <= $PageCount && !$FoundComment) {
						$this->CommentData = $PrivateMessages->GetCommentList($this->Context->Configuration['COMMENTS_PER_PAGE'], $this->CurrentPage, $this->DiscussionID);
						while ($Row = $this->Context->Database->GetRow($this->CommentData)) {
							if (ForceInt($Row['CommentID'], 0) == $Focus) {
								$FoundComment = 1;
								break;
							}
						}
						$this->CurrentPage++;
					}
					$this->Context->Database->RewindDataSet($this->CommentData);
				} else {
					$this->CommentData = $PrivateMessages->GetCommentList($this->Context->Configuration['COMMENTS_PER_PAGE'], $this->CurrentPage, $this->DiscussionID);
				}
			}

			if ($this->Discussion) {
				// Set up the pagelist
				$this->pl = $this->Context->ObjectFactory->NewContextObject($this->Context, 'PageList', 'DiscussionID', $this->Discussion->DiscussionID, CleanupString($this->Discussion->Name).'/');
				$this->pl->NextText = $this->Context->GetDefinition('Next');
				$this->pl->PreviousText = $this->Context->GetDefinition('Previous');
				$this->pl->CssClass = 'PageList';
				$this->pl->TotalRecords = $this->CommentDataCount;
				$this->pl->CurrentPage = $this->CurrentPage;
				$this->pl->RecordsPerPage = $this->Context->Configuration['COMMENTS_PER_PAGE'];
				$this->pl->PagesToDisplay = 10;
				$this->pl->PageParameterName = 'page';
				$this->pl->DefineProperties();
			}
		}

	   function Render() {
			$this->CallDelegate('PreRender');
			include(dirname(__FILE__) . '/message_view.php');
			$this->CallDelegate('PostRender');
	   }
	}

	class PrivateMessageForm extends PostBackControl {
		var $FatalError;
		var $EditDiscussionID;
		var $Discussion;
		var $DiscussionFormattedForDisplay;
		var $DiscussionID;
		var $Comment;
		var $CommentID;
		var $Form;
		var $Title;
		var $CommentFormAttributes;
		var $DiscussionFormAttributes;

		function PrivateMessageForm(&$Context) {
			$this->Name = 'PrivateMessageForm';
			$this->Constructor($Context);

			$this->CommentFormAttributes = '';
			$this->DiscussionFormAttributes = '';
			$this->PostBackAction = ForceIncomingString('Action', '');
			$this->FatalError = 0;
			$this->EditDiscussionID = 0;
			$this->CommentID = 0;
			$this->DiscussionID = ForceIncomingInt('DiscussionID', 0);
			$this->DiscussionFormattedForDisplay = 0;

			// Check permissions and make sure that the user can add comments/discussions
			// Make sure user can post
			if ($this->DiscussionID == 0 && $this->Context->Session->UserID == 0) {
				$this->Context->WarningCollector->Add($this->Context->GetDefinition('NoDiscussionsNotSignedIn'));
				$this->FatalError = 1;
			}

			$this->Comment = $this->Context->ObjectFactory->NewContextObject($this->Context, 'Comment');
			$this->Discussion = $this->Context->ObjectFactory->NewContextObject($this->Context, 'Discussion');

			$PrivateMessages = $this->Context->ObjectFactory->NewContextObject($this->Context, 'PrivateMessages');
			$cm = $this->Context->ObjectFactory->NewContextObject($this->Context, 'CommentManager');
			$dm = $this->Context->ObjectFactory->NewContextObject($this->Context, 'DiscussionManager');

			// If saving a discussion
			if ($this->PostBackAction == 'SaveDiscussion') {
				$this->Discussion->Clear();
				$this->Discussion->GetPropertiesFromForm($this->Context);
				$this->Discussion->DiscussionID = $this->EditDiscussionID;

				if (ForceIncomingString('WhisperUsername', '') == '') {
					$ResultDiscussion = false;
					$this->Context->WarningCollector->Add($this->Context->GetDefinition('ErrWhisperUsernameMandatory'));
				} else {
					$ResultDiscussion = $dm->SaveDiscussion($this->Discussion);
				}

				if ($ResultDiscussion) {
					// Mark as Read
					$Discussion = $PrivateMessages->GetDiscussionById($this->Discussion->DiscussionID, 1);
					$PrivateMessages->SendNotification($Discussion->WhisperUserID);
					header('location:'.GetUrl($this->Context->Configuration, 'extension.php', '', '', '', '', 'PostBackAction=PrivateMessages'));
					die();
				}

			// If saving a comment
			} elseif ($this->PostBackAction == 'SaveComment') {
				$this->Comment->Clear();
				$this->Comment->GetPropertiesFromForm();
				$this->Comment->DiscussionID = $this->DiscussionID;
				$this->Discussion = $PrivateMessages->GetDiscussionById($this->Comment->DiscussionID);
				$ResultComment = $cm->SaveComment($this->Comment);
				if ($ResultComment) {
					// Mark as Read
					$PrivateMessages->GetDiscussionById($this->DiscussionID, 1);
					if ($this->Discussion->WhisperUserID == $this->Context->Session->UserID) {
						$PrivateMessages->SendNotification($this->Discussion->AuthUserID);
					} else {
						$PrivateMessages->SendNotification($this->Discussion->WhisperUserID);
					}
					header('location:'.GetUrl($this->Context->Configuration, 'extension.php', '', '', '', '', 'PostBackAction=PrivateMessages'));
					die();
				}
			}
			if (!$this->IsPostBack && $this->Comment->DiscussionID == 0 && $this->Comment->CommentID == 0) {
				if (!$this->Discussion->Comment) $this->Discussion->Comment = $this->Context->ObjectFactory->NewContextObject($this->Context, 'Comment');

				$this->Discussion->Comment->FormatType = $this->Context->Session->User->DefaultFormatType;
				if ($this->Comment) $this->Comment->FormatType = $this->Context->Session->User->DefaultFormatType;
			}

			if ($this->Comment) $this->PostBackParams->Set('CommentID', $this->Comment->CommentID);
			$this->PostBackParams->Set('DiscussionID', $this->DiscussionID);
			$this->Title = $this->Context->GetDefinition('SendPrivateMessage');
			if ($this->EditDiscussionID > 0 || ($this->CommentID == 0 && $this->DiscussionID == 0)) {
				$this->Form = 'DiscussionForm';
			} else {
				$this->Form = 'CommentForm';
			}
		}

		function GetCommentForm($Comment) {
			$Comment->FormatPropertiesForDisplay(1);
			$this->PostBackParams->Set('PostBackAction', 'PrivateMessages');
			$this->PostBackParams->Set('View', 'SendMessage');
			$this->PostBackParams->Set('Action', 'SaveComment');
			$this->PostBackParams->Set('UserCommentCount', $this->Context->Session->User->CountComments);
			$this->PostBackParams->Set('AuthUserID', $Comment->AuthUserID);
			include(dirname(__FILE__) . '/message_form_reply.php');
		}

		function GetDiscussionForm($Discussion) {
			if (!$this->DiscussionFormattedForDisplay) $Discussion->FormatPropertiesForDisplay();
			$Discussion->Comment->FormatPropertiesForDisplay(1);
			$this->PostBackParams->Set('CommentID', $Discussion->FirstCommentID);
			$this->PostBackParams->Set('AuthUserID', $Discussion->AuthUserID);
			$this->PostBackParams->Set('UserDiscussionCount', $this->Context->Session->User->CountDiscussions);
			$this->PostBackParams->Set('PostBackAction', 'PrivateMessages');
			$this->PostBackParams->Set('View', 'SendMessage');
			$this->PostBackParams->Set('Action', 'SaveDiscussion');
			$this->PostBackParams->Set('CategoryID', ForceInt($this->Context->Configuration['PRIVATE_MESSAGES_CATEGORY_ID'], 0));
			include(dirname(__FILE__) . '/message_form_new.php');
		}

		function GetPostFormatting($SelectedFormatType) {
			$FormatCount = count($this->Context->StringManipulator->Formatters);
			$f = $this->Context->ObjectFactory->NewObject($this->Context, 'Radio');
			$f->Name = 'FormatType';
			$f->CssClass = 'FormatTypeRadio';
			$f->SelectedID = $SelectedFormatType;

			$this->DelegateParameters['FormatRadio'] = &$f;
			$ItemAppend = '';
			while (list($Name, $Object) = each($this->Context->StringManipulator->Formatters)) {
				$this->DelegateParameters['RadioItemName'] = &$Name;
				$this->DelegateParameters['RadioItemAppend'] = &$ItemAppend;
				$this->CallDelegate('PreFormatRadioItemAdd');
				$f->AddOption($Name, $this->Context->GetDefinition($Name), $ItemAppend);
				$ItemAppend = '';
			}
			$this->CallDelegate('PreFormatRadioRender');

			$sReturn = '';
			include(ThemeFilePath($this->Context->Configuration, 'post_formatter.php'));
			return $sReturn;
		}

		function Render() {
			if ($this->FatalError) {
				$this->Render_Warnings();
			} else {
				if ($this->Form == 'DiscussionForm') {
					$this->GetDiscussionForm($this->Discussion);
				} elseif ($this->Form == 'CommentForm') {
					$this->GetCommentForm($this->Comment);
				}
			}
		}
	}

	// Menu control isn't available in People
	if (isset($Menu)) {
		//$PrivateMessages = $Context->ObjectFactory->NewContextObject($Context, 'PrivateMessages');
		//$NewMessages = $PrivateMessages->GetNewMessagesCount();
		$TabName = $Context->GetDefinition('PrivateMessagesTab'); //. ' ('. $NewMessages.')';

		$Menu->AddTab($TabName, 'privatemessages', GetUrl($Configuration, 'extension.php', '', '', '', '', 'PostBackAction=PrivateMessages'), '', $Configuration['TAB_POSITION_PRIVATE_MESSAGES']);
	}

	if ($Context->SelfUrl == 'extension.php' && ForceIncomingString('PostBackAction', '') == 'PrivateMessages') {

		$Head->AddStyleSheet('extensions/PrivateMessages/style.css');
		$Menu->CurrentTab = 'privatemessages';
		$Context->PageTitle = $Context->GetDefinition('PrivateMessages');

		$Title = $Context->GetDefinition('PrivateMessages');
		$Panel->AddList($Title, 100);
		$Panel->AddListItem($Title, $Context->GetDefinition('Inbox'), GetUrl($Configuration, 'extension.php', '', '', '', '', 'PostBackAction=PrivateMessages'));
		$Panel->AddListItem($Title, $Context->GetDefinition('SentMail'), GetUrl($Configuration, 'extension.php', '', '', '', '', 'PostBackAction=PrivateMessages&View=SentMail'));
		$Panel->AddString('<h1><a href="'.GetUrl($Configuration, 'extension.php', '', '', '', '', 'PostBackAction=PrivateMessages&View=SendMessage').'">'.$Context->GetDefinition('SendPrivateMessage').'</a></h1>');
		$Panel->AddListItem($Title, $Context->GetDefinition('Options'), GetUrl($Context->Configuration, 'account.php', '', '', '', '', 'PostBackAction=Functionality'));

		switch (ForceIncomingString('View', 'Inbox')) {

			case 'Inbox':
			case 'SentMail':
				$PrivateMessagesGrid = $Context->ObjectFactory->NewContextObject($Context, 'PrivateMessagesGrid');
				$Page->AddRenderControl($PrivateMessagesGrid, $Configuration['CONTROL_POSITION_BODY_ITEM']);
				break;

			case 'Message':
				$PrivateMessageView = $Context->ObjectFactory->CreateControl($Context, 'PrivateMessageView');
				$PrivateMessageForm = $Context->ObjectFactory->CreateControl($Context, 'PrivateMessageForm');
				$PrivateMessageForm->Discussion = &$PrivateMessageView->Discussion;
				$Page->AddRenderControl($PrivateMessageView, $Configuration['CONTROL_POSITION_BODY_ITEM']);
				$Page->AddRenderControl($PrivateMessageForm, $Configuration['CONTROL_POSITION_BODY_ITEM'] + 10);
				break;

			case 'SendMessage':
				$PrivateMessageForm = $Context->ObjectFactory->CreateControl($Context, 'PrivateMessageForm');
				$Page->AddRenderControl($PrivateMessageForm, $Configuration['CONTROL_POSITION_BODY_ITEM']);
				break;
		}
	}

	if ($Context->SelfUrl == 'account.php') {
		$AccountUserID = ForceIncomingInt('u', $Context->Session->UserID);
		if (!@$UserManager) $UserManager = $Context->ObjectFactory->NewContextObject($Context, "UserManager");
		if (!@$AccountUser) $AccountUser = $UserManager->GetUserById($AccountUserID);
		$AccountOptions = $Context->GetDefinition('AccountOptions');
		$Panel->AddListItem($AccountOptions, $Context->GetDefinition('SendPrivateMessage'), GetUrl($Context->Configuration, 'extension.php', '', '', '', '', 'PostBackAction=PrivateMessages&View=SendMessage&SendTo='.urlencode($AccountUser->Name)), '', '', 1);
	}
}

if ($Context->SelfUrl == "settings.php" && $Context->Session->User->Permission('PERMISSION_CHANGE_APPLICATION_SETTINGS')) {

	class PrivateMessagesSettingsForm extends PostBackControl {
		var $ConfigurationManager;
		var $CategorySelect;

		function PrivateMessagesSettingsForm(&$Context) {
			$this->Name = 'PrivateMessagesSettingsForm';
			$this->ValidActions = array('PrivateMessages', 'ProcessPrivateMessages');
			$this->Constructor($Context);

			$CategoryManager = $this->Context->ObjectFactory->NewContextObject($this->Context, 'CategoryManager');
			$CategoryData = $CategoryManager->GetCategories(1, 0, 0);


			if (!$this->Context->Session->User->Permission('PERMISSION_CHANGE_APPLICATION_SETTINGS')) {
				$this->IsPostBack = 0;
			} elseif( $this->IsPostBack ) {
				$SettingsFile = $this->Context->Configuration['APPLICATION_PATH'].'conf/settings.php';
				$this->ConfigurationManager = $this->Context->ObjectFactory->NewContextObject($this->Context, 'ConfigurationManager');
				if ($this->PostBackAction == 'ProcessPrivateMessages') {
					$this->ConfigurationManager->GetSettingsFromForm($SettingsFile);
					// And save everything
					if ($this->ConfigurationManager->SaveSettingsToFile($SettingsFile)) {
						header('location: '.GetUrl($this->Context->Configuration, 'settings.php', '', '', '', '', 'PostBackAction=PrivateMessages&Success=1'));
					} else {
						$this->PostBackAction = 'PrivateMessages';
					}
				}
			}

			$this->CategorySelect = $this->Context->ObjectFactory->NewObject($this->Context, 'Select');
			$this->CategorySelect->Name = 'PRIVATE_MESSAGES_CATEGORY_ID';
			$this->CategorySelect->CssClass = 'SmallInput';
			$this->CategorySelect->AddOptionsFromDataSet($this->Context->Database, $CategoryData, 'CategoryID', 'Name');
			if (array_key_exists('PRIVATE_MESSAGES_CATEGORY_ID', $this->Context->Configuration)) {
				$this->CategorySelect->SelectedValue = $this->Context->Configuration['PRIVATE_MESSAGES_CATEGORY_ID'];
			}
			$this->CallDelegate('Constructor');
		}

		function Render() {
			if ($this->IsPostBack) {
				$this->CallDelegate('PreRender');
				$this->PostBackParams->Clear();
				if ($this->PostBackAction == 'PrivateMessages') {
					$this->PostBackParams->Set('PostBackAction', 'ProcessPrivateMessages');
					echo '
					<div id="Form" class="Account PrivateMessagesSettings">
					<fieldset>
						<legend>'.$this->Context->GetDefinition("PrivateMessagesSettings").'</legend>
						'.$this->Get_Warnings().'
						'.$this->Get_PostBackForm('frmPrivateMessages').'
						<h2>'.$this->Context->GetDefinition("PrivateMessagesCategory").'</h2>
						<p>'.$this->Context->GetDefinition("PrivateMessagesCategoryNotes").'</p>
						<ul>
							<li>
								<label for="sCategorySelect">'.$this->Context->GetDefinition('Categories').'</label>
								'.$this->CategorySelect->Get().'
							</li>
						</ul>
						<div class="Submit">
							<input type="submit" name="btnSave" value="'.$this->Context->GetDefinition('Save').'" class="Button SubmitButton" />
							<a href="'.GetUrl($this->Context->Configuration, $this->Context->SelfUrl).'" class="CancelButton">'.$this->Context->GetDefinition('Cancel').'</a>
						</div>
						</form>
					</fieldset>
					</div>';
				}
			}
			$this->CallDelegate('PostRender');
		}
	}

	$PrivateMessagesSettingsForm = $Context->ObjectFactory->NewContextObject($Context, 'PrivateMessagesSettingsForm');
	$Page->AddRenderControl($PrivateMessagesSettingsForm, $Configuration['CONTROL_POSITION_BODY_ITEM'] + 1);

	$ExtensionOptions = $Context->GetDefinition('ExtensionOptions');
	$Panel->AddList($ExtensionOptions, 10);
	$Panel->AddListItem($ExtensionOptions, $Context->GetDefinition('PrivateMessagesSettings'), GetUrl($Context->Configuration, 'settings.php', '', '', '', '', 'PostBackAction=PrivateMessages'));
}

// Preferences
if ($Context->SelfUrl == 'account.php') {
	$Context->AddToDelegate('PreferencesForm', 'PreRender', 'PreferencesForm_PrivateMessages');
	function PreferencesForm_PrivateMessages(&$PreferencesForm) {
		$PreferencesForm->AddPreference('PrivateMessages', 'PrivateMessageNotification', 'PrivateMessageNotification');
	}
}

// Deactivate original whisper system
if ($Context->Configuration['PRIVATE_MESSAGES_DISABLE_WHISPERS'] == '1') {

	function DiscussionForm_DisableWhispers(&$CommentForm) {
		$CommentForm->Context->Configuration['ENABLE_WHISPERS'] = '0';
	}

	function DiscussionForm_EnableWhispers(&$CommentForm) {
		$CommentForm->Context->Configuration['ENABLE_WHISPERS'] = '1';
	}

	// Delegates
	$Context->AddToDelegate('DiscussionForm', 'CommentForm_PreWhisperInputRender', 'DiscussionForm_DisableWhispers');
	$Context->AddToDelegate('DiscussionForm', 'CommentForm_PreCommentsInputRender', 'DiscussionForm_EnableWhispers');
	$Context->AddToDelegate('DiscussionForm', 'DiscussionForm_PreTopicRender', 'DiscussionForm_DisableWhispers');
	$Context->AddToDelegate('DiscussionForm', 'DiscussionForm_PreCommentRender', 'DiscussionForm_EnableWhispers');
}
?>